package cn.etynit.pet.service.impl;

import cn.etynit.basic.config.BussinessException;
import cn.etynit.basic.domain.Point;
import cn.etynit.basic.util.*;
import cn.etynit.order.domain.OrderPetAcquisition;
import cn.etynit.order.service.IOrderPetAcquisitionService;
import cn.etynit.org.domain.Employee;
import cn.etynit.org.domain.Shop;
import cn.etynit.org.mapper.ShopMapper;
import cn.etynit.org.service.EmployeeService;
import cn.etynit.org.service.IShopService;
import cn.etynit.pet.domain.SearchMasterMsg;
import cn.etynit.pet.domain.SearchMasterMsgAuditLog;
import cn.etynit.pet.dto.AcceptDto;
import cn.etynit.pet.dto.AllocationDto;
import cn.etynit.pet.dto.ReturnDto;
import cn.etynit.pet.mapper.SearchMasterMsgAuditLogMapper;
import cn.etynit.pet.mapper.SearchMasterMsgMapper;
import cn.etynit.pet.query.SearchMasterMsgQuery;
import cn.etynit.pet.service.ISearchMasterMsgService;
import cn.etynit.basic.service.impl.BaseServiceImpl;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.internet.MimeMessage;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author etynit
 * @since 2022-11-01
 */
@Service
public class SearchMasterMsgServiceImpl extends BaseServiceImpl<SearchMasterMsg> implements ISearchMasterMsgService {

    @Autowired
    private SearchMasterMsgMapper searchMasterMsgMapper;

    @Autowired
    private SearchMasterMsgAuditLogMapper searchMasterMsgAuditLogMapper;

    @Autowired
    private IShopService shopService;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private IOrderPetAcquisitionService orderPetAcquisitionService;

    @Autowired
    private JavaMailSender sender;

    /**
     * 注入rocketMQ对象
     */
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 宠物寻主发布
     * @param searchMasterMsg
     * @return
     */
    @Override
    public AjaxResult publish(SearchMasterMsg searchMasterMsg) {
        // 1.直接保存寻主消息，默认状态为待审核
        searchMasterMsgMapper.add(searchMasterMsg);
        // 2.参数为空校验
        paramCheck(searchMasterMsg);
        // 3.百度AI审核&如果有企业定制审核还需要使用定制审核
        baiduAiCheck(searchMasterMsg);
        // 4.成功，根据用户填写的地址找方圆50公里内的最近的店铺，设置shopId，没找到就不管
        // 工具类DistanceUtil的getPoint方法传入地址得到经纬度对象
        Point point = DistanceUtil.getPoint(searchMasterMsg.getAddress());
        // 获取到所有的店铺
        List<Shop> shops = shopService.findAll();
        // 工具类DistanceUtil的getNearestShop传入经纬度已经查询到的店铺集合得到店铺对象
        Shop shop = DistanceUtil.getNearestShop(point, shops);
        // 如果查询到店铺，就绑定店铺id
        if (shop != null){
            searchMasterMsg.setShopId(shop.getId());
        }
        // 5.修改状态为审核通过
        searchMasterMsg.setState(1);
        // 6.调用数据库进行修改
        searchMasterMsgMapper.update(searchMasterMsg);
        return AjaxResult.me().success();
    }

    /**
     * 查询店铺待处理数据
     * @param searchMasterMsg
     * @return
     */
    @Override
    public PageList<SearchMasterMsg> selectSearchMasterMessageByParam(SearchMasterMsgQuery searchMasterMsg) {
        // 查询数据总条数
        Integer totals = searchMasterMsgMapper.selectSearchMasterMessageByParamQueryCount(searchMasterMsg);
        // 如果数据是空，返回空数组
        if (null == totals || 0 == totals){
            return new PageList<>(0,new ArrayList<>());
        }
        // 查询总数据
        List<SearchMasterMsg> searchMasterMsgs = searchMasterMsgMapper.selectSearchMasterMessageByParam(searchMasterMsg);
        // 返回
        return new PageList<>(totals,searchMasterMsgs);
    }

    /**
     * 拒单
     * @param msgId
     * @param employee
     */
    @Override
    public void reject(Long msgId, Employee employee) {
        // 根据消息Id查询寻主消息
        SearchMasterMsg searchMasterMsg = searchMasterMsgMapper.findById(msgId);
        // 判断该寻主消息是否为空，为空抛异常
        if (null == searchMasterMsg){
            throw new BussinessException("寻主消息不存在，请重新操作！");
        }
        // 将shopId置空，放回寻主池
        searchMasterMsg.setShopId(null);
        // 更新寻主信息,注意！更新setShopId在sql里面有判断不为null的if判断，需要更改！
        searchMasterMsgMapper.update(searchMasterMsg);
        // 4.@TODO 添加拒单日志，自己去做，我也不确定有没有表，没有就创建，如果做的好一点，还要让平台管理员审核，审核通过看情况扣不扣分
    }


    /**
     * 接单
     * @param acceptDto
     */
    @Override
    public void accept(AcceptDto acceptDto) {
        // 根据消息Id查询寻主消息
        SearchMasterMsg searchMasterMsg = searchMasterMsgMapper.findById(acceptDto.getMsgId());
        // 判断寻主消息是否为null，如果为null，抛出异常
        if (null == searchMasterMsg){
            throw new BussinessException("寻主消息不存在，请重新操作！");
        }
        // 需要解决线程安全问题，每次请求过来获取到的searchMasterMsg对象是不一样的，所以不能给对象上锁，所有寻主消息对象对应的id是唯一的，我们是给寻主消息的id上锁
        synchronized (searchMasterMsg.getId()){
            // 通过前端传递的参数获取到当前操作接单的员工
            Employee employee = employeeService.findById(acceptDto.getHandler());
            // 如果该员工不存在，抛异常
            if (null == employee){
                throw new BussinessException("不存在此员工，请重新操作！");
            }
            // 如果该寻主消息的状态是1（待处理），并且他所对应的shopId和操作该数据的员工的shopId一样，证明是此店铺的员工在接单
            if (searchMasterMsg.getState() == 1 && searchMasterMsg.getShopId().equals(employee.getShopId())){
                // 修改寻主消息的状态为2（已接单）
                searchMasterMsg.setState(2);
                // 更新信息
                searchMasterMsgMapper.update(searchMasterMsg);
                // 生成回购单
                initOrderPetAcquisition(acceptDto, searchMasterMsg, employee);
            }
        }

    }



    /**
     * 审核
     * @param id
     * @param employee
     */
    @Override
    public void risePetMsg(Long id, Employee employee) {
        // 审核校验的方法
        // 根据消息Id查询寻主消息
        SearchMasterMsg searchMasterMsgMapperById = searchMasterMsgMapper.findById(id);
        // 判断寻主消息是否为null，如果为null，抛出异常
        if (null == searchMasterMsgMapperById){
            throw new BussinessException("寻主消息不存在，请重新操作！");
        }
        // 如果该员工不存在，抛异常
        if (null == employee){
            throw new BussinessException("不存在此员工，请重新操作！");
        }
        // 工具类DistanceUtil的getPoint方法传入地址得到经纬度对象
        if (null == searchMasterMsgMapperById.getAddress() || "".equals(searchMasterMsgMapperById.getAddress())){
            throw new BussinessException("地址不存在，请核实！");
        }
        Point point = DistanceUtil.getPoint(searchMasterMsgMapperById.getAddress());
        // 获取到所有的店铺
        List<Shop> shops = shopService.findAll();
        // 工具类DistanceUtil的getNearestShop传入经纬度已经查询到的店铺集合得到店铺对象
        Shop shop = DistanceUtil.getNearestShop(point, shops);
        // 如果查询到店铺，就绑定店铺id
        if (shop != null){
            searchMasterMsgMapperById.setShopId(shop.getId());
        }
        // 修改状态为审核通过
        searchMasterMsgMapperById.setState(1);
        // 调用数据库进行修改
        searchMasterMsgMapper.update(searchMasterMsgMapperById);
    }




    /**
     * 审核不通过
     * @param returnDto
     * @param employee
     */
    @Override
    public void returnMsg(ReturnDto returnDto, Employee employee) {
        // 审核校验的方法
//        SearchMasterMsg searchMasterMsgMapperById = checking(returnDto, employee);
        // 发送邮件告知用户审核不通过，前往个人中心修改
//        // 1.创建复杂邮件对象
//        MimeMessage mimeMessage = sender.createMimeMessage();
//        // 2.发送复杂邮件的工具类
//        MimeMessageHelper helper = null;
//        try {
//            helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
//            helper.setFrom("wang155775@qq.com");
//            helper.setSubject("宠物直接审核结果通知");
//            // 3.设置文本内容，第二个参数 true 代表是否是一个html内容
//            helper.setText("<h1>恭喜您审核您审核通过，点击下方链接激活店铺</h1>"+
//                    "http://localhost:8080/shop/active/",true);
//            helper.setTo("wang155775@qq.com");
//        } catch (Exception e){
//            throw new BussinessException("发送邮件错误！");
//        }
//        sender.send(mimeMessage);
        // 根据消息Id查询寻主消息
        SearchMasterMsg searchMasterMsgMapperById = searchMasterMsgMapper.findById(returnDto.getMsgId());
        // 判断寻主消息是否为null，如果为null，抛出异常
        if (null == searchMasterMsgMapperById){
            throw new BussinessException("寻主消息不存在，请重新操作！");
        }
        // 如果该员工不存在，抛异常
        if (null == employee){
            throw new BussinessException("请登录后再进行操作！");
        }
        // 修改状态为审核通过
        searchMasterMsgMapperById.setState(1);
        // 调用数据库进行修改
        searchMasterMsgMapper.update(searchMasterMsgMapperById);
        // 添加日志
        SearchMasterMsgAuditLog searchMasterMsgAuditLog = new SearchMasterMsgAuditLog();
        // 添加消息id
        searchMasterMsgAuditLog.setMsgId(returnDto.getMsgId());
        // 状态
        searchMasterMsgAuditLog.setState(3);
        // 审核人
        searchMasterMsgAuditLog.setAuditId(employee.getId());
        // 审核日志
        searchMasterMsgAuditLog.setNote(returnDto.getNote());
        // 更新日志表
        searchMasterMsgAuditLogMapper.add(searchMasterMsgAuditLog);
    }

    /**
     * 将寻主消息分配到店铺
     * @param allocationDto
     * @param employee
     */
    @Override
    public void allocation(AllocationDto allocationDto, Employee employee) {
        Long shopId = allocationDto.getShop().getId();
        if (null == shopId){
            throw new BussinessException("您没有给该寻主消息分配店铺！");
        }

        if (null == allocationDto.getTitle() || "".equals(allocationDto.getTitle())){
            throw new BussinessException("寻主标题不能为空！");
        }

        if (null == allocationDto.getName() || "".equals(allocationDto.getName())){
            throw new BussinessException("宠物名称不能为空！");
        }

        if (null == allocationDto.getPrice()){
            throw new BussinessException("售价不能为空");
        }

        if (null == allocationDto.getAge()){
            throw new BussinessException("宠物年龄不能为空");
        }

        if (null == allocationDto.getCoatColor() || "".equals(allocationDto.getCoatColor())){
            throw new BussinessException("宠物毛色没有填！");
        }

        if (null == allocationDto.getAddress() || "".equals(allocationDto.getAddress())){
            throw new BussinessException("你是不是不填地址？");
        }
        SearchMasterMsg searchMasterMsg = new SearchMasterMsg();
        searchMasterMsg.setId(allocationDto.getId());
        searchMasterMsg.setShopId(shopId);
        searchMasterMsg.setTitle(allocationDto.getTitle());
        searchMasterMsg.setName(allocationDto.getName());
        searchMasterMsg.setAge(allocationDto.getAge());
        searchMasterMsg.setPrice(allocationDto.getPrice());
        searchMasterMsg.setCoatColor(allocationDto.getCoatColor());
        searchMasterMsg.setAddress(allocationDto.getAddress());
        searchMasterMsg.setState(1);
        searchMasterMsgMapper.update(searchMasterMsg);
    }






















    /**
     * 保存回购单的方法
     * @param acceptDto
     * @param searchMasterMsg
     * @param employee
     */
    private void initOrderPetAcquisition(AcceptDto acceptDto, SearchMasterMsg searchMasterMsg, Employee employee) {
        // 创建回购单对象
        OrderPetAcquisition orderPetAcquisition = new OrderPetAcquisition();
        // 生成订单编号，调用工具类CodeGenerateUtils的generateOrderSn方法随机生成
        orderPetAcquisition.setOrderSn(CodeGenerateUtils.generateOrderSn(acceptDto.getHandler()));
        // 添加摘要
        orderPetAcquisition.setDigest(acceptDto.getNote());
        // 最后处理时间，获取当前时间戳+3天的时间
        orderPetAcquisition.setLastcomfirmtime(new Date(System.currentTimeMillis() + 3 * 24 * 60 * 60 * 1000));
        // 设置状态为0，待处理
        orderPetAcquisition.setState(0);
        // 此時的钱就是用户发布的价格，要注意此金额不是最终金额，要以实际交易金额为准
        orderPetAcquisition.setPrice(new BigDecimal(searchMasterMsg.getPrice()));
        // 添加用户id
        orderPetAcquisition.setUserId(searchMasterMsg.getUserId());
        // 添加店铺id
        orderPetAcquisition.setShopId(employee.getShopId());
        // 添加收购宠物地址
        orderPetAcquisition.setAddress(searchMasterMsg.getAddress());
        // 添加员工id
        orderPetAcquisition.setEmpId(employee.getId());
        orderPetAcquisition.setSearchMasterMsgId(searchMasterMsg.getId());
        // 添加到回购表
        orderPetAcquisitionService.add(orderPetAcquisition);

        /**
         * 生产者
         */
        rocketMQTemplate.asyncSend("petome_topic", MessageBuilder.withPayload(orderPetAcquisition.getOrderSn()).build(),
                new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.println("成功！"+sendResult);
                    }

                    @Override
                    public void onException(Throwable throwable) {
                        System.out.println("失败！"+throwable.getMessage());
                    }
                }, 3000, 3);
    }


    // 参数校验方法
    private void paramCheck(SearchMasterMsg searchMasterMsg) {
        // 判断如果发布的寻主信息名字以及地址是空
        if(StringUtils.isEmpty(searchMasterMsg.getName()) || StringUtils.isEmpty(searchMasterMsg.getAddress())){
            // 创建一个SearchMasterMsgAuditLog对象
            SearchMasterMsgAuditLog searchMasterMsgAuditLog = new SearchMasterMsgAuditLog();
            // 添加Id
            searchMasterMsgAuditLog.setMsgId(searchMasterMsg.getId());
            // 添加失败信息
            searchMasterMsgAuditLog.setNote("审核失败！添加的参数不能为空，请前往个人中心修改发布");
            // 添加日志表
            searchMasterMsgAuditLogMapper.add(searchMasterMsgAuditLog);
            throw new BussinessException("审核失败！添加的参数不能为空，请前往个人中心修改发布");
        }
    }

    // 百度AI校验方法
    private void baiduAiCheck(SearchMasterMsg searchMasterMsg) {
        // new一个字符串，把我们需要校验的文本内容拼接到字符串调用百度AI一次性校验
        StringBuilder sbr = new StringBuilder();
        sbr.append(searchMasterMsg.getName())
                .append(searchMasterMsg.getAddress())
                .append(searchMasterMsg.getTitle());
        // 调用百度AI工具类，如果审核不通过，添加日志
        if (!BaiduAuditUtils.TextCensor(sbr.toString())){
            SearchMasterMsgAuditLog searchMasterMsgAuditLog = new SearchMasterMsgAuditLog();
            searchMasterMsgAuditLog.setMsgId(searchMasterMsg.getId());
            searchMasterMsgAuditLog.setNote("审核失败！内容涉及违规，请前往个人中心修改发布");
            searchMasterMsgAuditLogMapper.add(searchMasterMsgAuditLog);
            throw new BussinessException("审核失败！内容涉及违规，请前往个人中心修改发布");
        }
    }
}
